系列:從現場踩坑到 AI 工具 — IT Diagnostic Agent 開發實錄
工具在 6 月 10 日上 GitHub。
隔天,Issue #1 就來了。
標題:設定 gemini api key 仍無法使用
回報者:tskerpnext
我打開來看的時候,第一個反應不是「有 bug」,是**「這內容不太像一般的 bug report」**。
回報者沒有只寫「我填了 Gemini Key 但不能用」。
他寫的是:
claude 回答
已修正。原因是:在設定視窗裡切到 Gemini 分頁並儲存 API Key 時,程式只把金鑰存進 localStorage,但沒有把目前使用的 provider 切換成 Gemini(預設一直是 Claude)。所以狀態列還是在檢查 Claude 的 key(是空的),就一直顯示「未設定 API Key」。
他自己拿 Claude 去診斷了我的工具,然後把根本原因分析貼給我。
而且他還附上了具體的 diff:
1116 localStorage.setItem('it_ep_ollama', providers.ollama.endpoint);
1117 + currentProvider = modalTab;
1118 + localStorage.setItem('it_provider', currentProvider);
1119 updateStatus();
1120 closeModal();
兩行程式碼。位置精確到行號。
我照著改了,commit 0dc4d22,當天結案。
把整條鏈拉出來看:
我用 Claude 做了這個工具
↓
一個陌生人拿去用,撞到 bug
↓
他用 Claude 找出根本原因
↓
他把分析和 diff 給我
↓
我改掉,推上 main
一個 Claude 協作做出來的工具,被一個陌生人用 Claude 診斷,然後修好了。
我不知道該怎麼形容這個感覺。它不是「AI 取代了什麼」,而是整條協作鏈上的每一個人,都各自帶著自己的 AI 在工作。
而結果是:一個 bug 從發現到修好,不到二十四小時,跨越兩個互不相識的人和二個國家。
回頭看,這個 bug 的成因很典型:它是「從單一供應商改成多供應商」那次重構留下的洞。
原本只支援 Claude 的時候,currentProvider 這個概念根本不需要——反正只有一個。
改成四家之後,儲存設定的流程漏掉了「順便把 currentProvider 切過去」這一步。所以資料存對了,但狀態列在看錯的地方。
而有趣的是——Day 11 核對程式碼時撿到的那段向下相容邏輯:
// Backward compat: migrate old single apiKey
if(!providers.claude.key && localStorage.getItem('it_key')) {
它跟這個 bug 出自同一次重構。
同一次改動留下了兩個產物:一個是防禦性的(幫舊使用者搬遷 Key),一個是有洞的(忘記切 provider)。
我當時想到了資料要搬遷,但沒想到狀態要同步。
重構的風險不在你想到的地方,在你以為不存在的概念上。 currentProvider 在單一供應商時代不存在,所以我沒有把它列進檢查清單。
6 月 15 日,kuang1963 開了 Issue #2。
標題:關於 ollama 本地模型出現 回應: Failed to fetch
內容同樣直接命中:
Ollama 沒有開啟 CORS 跨網域存取。it-diagnostic-agent 是透過瀏覽器網頁執行的,網頁會因為安全性限制,無法直接存取沒有允許 CORS 的後端 API。
解決方法:你需要設定環境變數
OLLAMA_ORIGINS="*"來允許所有連線。
他說對了。
而這件事讓我發現一個我自己漏掉的東西。
Day 20 講過本地模型的混合內容問題:GitHub Pages 是 HTTPS,localhost:11434 是 HTTP,瀏覽器禁止 HTTPS 頁面請求 HTTP 資源。
Issue #2 講的是另一件事:Ollama 自己預設不允許跨來源請求,需要設 OLLAMA_ORIGINS。
這是兩個獨立的問題,但它們的症狀完全一樣:Failed to fetch。
| 混合內容 | CORS | |
|---|---|---|
| 誰在擋 | 瀏覽器(HTTPS→HTTP) | Ollama(未授權來源) |
| 怎麼解 | 用 file:// 開啟本機檔案 |
設 OLLAMA_ORIGINS |
| 我做了什麼 | 寫進確認 modal | 原本什麼都沒做 |
我在做那個 Ollama 確認 modal 的時候(Day 20),checklist 裡寫了安裝、ollama serve、ollama pull、端點設定、防火牆、OLLAMA_HOST=0.0.0.0——
但沒有 OLLAMA_ORIGINS。
我想到了「Ollama 要能被連到」(OLLAMA_HOST),沒想到「Ollama 要允許誰來連」(OLLAMA_ORIGINS)。
這兩件事聽起來很像,但一個是網路可達性,一個是來源授權。而我在做 IT 二十年,這個區別我應該最熟。
我在 Issue #2 底下寫了完整的解法,按作業系統分開:
Windows(PowerShell)
$env:OLLAMA_ORIGINS="*"
ollama serve
永久設定:
[System.Environment]::SetEnvironmentVariable('OLLAMA_ORIGINS', '*', 'User')
macOS / Linux
OLLAMA_ORIGINS="*" ollama serve
macOS 永久設定(透過 launchctl):
launchctl setenv OLLAMA_ORIGINS "*"
為什麼要分作業系統寫?
因為「設環境變數」這句話在三個系統上是三種完全不同的操作。而回報者不一定用的是我用的系統。
這是我在 Day 12 講的規則 2 的實際應用:給出下一個具體動作,而不是給出方向。 「你需要設定環境變數」是方向,「在 PowerShell 貼這行」是動作。
然後我在最後說:我會把這個補進 README 的疑難排解章節。
README 現在有這一段:
Ollama 出現
Failed to fetch這是 Ollama 的 CORS(跨來源資源共用)限制造成的……
四個系統的指令都在裡面。但我還加了一段回報者沒提到的:
⚠️ 安全提醒:
OLLAMA_ORIGINS="*"允許所有來源連線,適合個人或內網環境。若是正式部署,建議改為指定來源,例如OLLAMA_ORIGINS="https://你的網域"。
* 是萬用字元,意思是「任何網站都可以呼叫你的 Ollama」。在自己筆電上沒差,在公司內網的 Ollama Server 上就是一個開放的端點。
回報者給的是能動的解法。我補的是能動但別把自己弄危險的解法。
這是我在這兩個 Issue 裡唯一真正加值的地方。 他們兩位都比我更快找到技術原因——一個用了 Claude,一個直接就懂 CORS。
而我能補的,是二十年來看過太多「先能用再說」最後變成資安缺口的經驗。
順著這條線講 README 的演進:
第一版 — 純繁體中文,講工具是什麼、怎麼用。
因為工具本來就只有繁中(Day 08)。
第二版 — 加英文版。
因為工具加了英文介面,README 不同步很奇怪。而且放上 GitHub 之後,有看不懂中文的人來看。
第三版 — 加疑難排解章節。
因為有了真實使用者,才知道什麼地方會卡。
第三版是最重要的一版,而它的內容我完全寫不出來——因為我自己不會遇到那些問題。
我的 Gemini Key 一直是好的(所以我沒撞到 Issue #1)。我開發時都用 file:// 開本機檔案(所以我沒撞到混合內容)。我的 Ollama 是我自己裝的,環境變數早就設好了(所以我沒撞到 CORS)。
開發者是這個世界上最不可能遇到自己軟體的環境問題的人。
因為我們的環境是我們自己養出來的。
可控 vs 不可控
我控制不了使用者的環境有多千奇百怪。我控制得了 README 的疑難排解章節有多完整。
而唯一能填滿那個章節的方式,是等別人來撞。
核心 vs 外部
兩個 Issue 表面上都是外部環境問題(Key 沒切、CORS 沒開)。
但 Issue #1 的核心是我的重構有洞。Issue #2 的核心是我的 checklist 漏了一項。
外部問題往往是核心疏失的症狀。 如果我只回答「你去設 OLLAMA_ORIGINS」就結案,那 modal 裡那個缺口到今天還在。
(後記:那個缺口已經補上了。 本機部署和區網部署兩份 checklist 都加了 OLLAMA_ORIGINS 這一項,而且直接把 Failed to fetch 這個症狀寫進去——因為使用者撞到錯誤時會回來對照清單,看到症狀比看到設定名稱更能對上。修正跟 Day 15 那兩行是同一個 commit:d2455c0。)
已成立 vs 假設
「我的工具能用」在有人回報之前,只是一個在我自己電腦上成立的假設。
我原本以為開源之後最需要的是推廣。
實際上最有價值的是兩個陌生人願意花時間告訴我哪裡壞了。
Issue #1 那個人不只回報,還做了根本原因分析、給了行號精確的 diff。Issue #2 那個人直接指出 CORS 並給了解法。
他們沒有義務這樣做。
開源專案真正的資產不是 Star 數,是有人願意幫你看。
而下一篇我要面對的,剛好就是 Star 數這件事——因為我原本對它的解讀,現在被數據推翻了。
明天預告: 六月的時候,我的 Fork 數一直比 Star 多,我把它解讀成「有人在部署,不是收藏」。兩個月後我回去看數字,那個模式反轉了。而還有一個數字是 0。
作者:Rich Chang | IT 基礎建設工程師 | 越南・柬埔寨・台灣